package com.server.questionbank.snframe.util.FileUtil.operation.multipart;

import com.server.questionbank.snframe.util.FileUtil.operation.multipart.chunk.DownloadChunkOperation;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;

/**
 * 分片下载实现
 */
@Slf4j
public class MultipartDownloadOperation extends MultipartOperation {
    private final File targetFile;
    private final RandomAccessFile raf;
    private final long fileSize;
    
    public MultipartDownloadOperation(MinioClient minioClient, String bucket, String object,
            File targetFile, int chunkSize) throws Exception {
        super(minioClient, bucket, object, chunkSize);
        this.targetFile = targetFile;
        
        // 获取文件信息
        StatObjectResponse stat = minioClient.statObject(
            StatObjectArgs.builder()
                .bucket(bucket)
                .object(object)
                .build()
        );
        this.fileSize = stat.size();
        
        // 创建随机访问文件
        this.raf = new RandomAccessFile(targetFile, "rw");
        this.raf.setLength(fileSize);
    }
    
    @Override
    public void execute() throws Exception {
        try {
            List<Future<Void>> futures = new ArrayList<>();
            long offset = 0;
            int partNumber = 1;
            
            // 分片下载
            while (offset < fileSize) {
                long length = Math.min(chunkSize, fileSize - offset);
                futures.add(executor.submit(new DownloadChunkOperation(
                    minioClient, bucket, object, raf, offset, length, partNumber++
                )));
                offset += chunkSize;
            }
            
            // 等待所有分片下载完成
            for (Future<Void> future : futures) {
                future.get();
            }
            
        } catch (Exception e) {
            log.error("分片下载失败: {}", e.getMessage(), e);
            // 下载失败时删除目标文件
            raf.close();
            targetFile.delete();
            throw e;
        } finally {
            raf.close();
            shutdown();
        }
    }
}